package jp.co.redfox.archclub.poker.hand;

import java.util.List;

import jp.co.redfox.archclub.poker.Card;
import jp.co.redfox.archclub.poker.Hand;

public class OnePair {

    private Pair pair;
    private final List<Card> notPair;

    public static OnePair createHand(Hand hand){
        OnePairJudgeState currentState = new InitialState();
       
        // use state change pattern
        for(Card card: hand.getCards())
            currentState = currentState.change(card);
        
        if(GoalState.isGoal(currentState))
            return new OnePair(currentState.getPair(), currentState.getNotPair);
    }

    private abstract class OnePairJudgeState implements HandJudgeState{
        @Override
        public abstract OnePairJudgeState change(Card card);
        private Pair getPair(){
            return pair;
        }
        private List<Card> getNotPair(){
            return notPair;
        }
    }
    private OnePair(Pair pair, List<Card> notPair){
        this.pair = pair;
        this.notPair = notPair;
    }
    
    private class InitialState extends OnePairJudgeState{

        @Override
        public OnePairJudgeState change(Card card) {
            notPair.add(card);
            return new NoPairState();
        }   
    }
    private class NoPairState extends OnePairJudgeState{

        @Override
        public OnePairJudgeState change(Card nextCard) {
            for(Card card:notPair)
                if(card.sameNumber(nextCard)){
                    notPair.remove(card);
                    pair = Pair.createPair(card, nextCard);
                    return new PairState();
                }
            if(notPair.size() == (Hand.HAND_NUMBER - 1))
                return NotApplicableState.getInstance();
              return this;
        }
        
    }
    private class PairState extends OnePairJudgeState{

        @Override
        public OnePairJudgeState change(Card nextCard) {
            if(pair.getNumber().equals(nextCard.getNumber()))
                return NotApplicableState.getInstance();

            for(Card card:notPair)
                if(card.sameNumber(nextCard))
                    return NotApplicableState.getInstance();                    
            
            if(notPair.size() == Hand.HAND_NUMBER - 3)
                return GoalState.getInstance();
            
            notPair.add(nextCard);
            return this;
        }

    }
    
}
